package com.zxd.interview.spring;

import com.zxd.interview.sort.AddTest;
import com.zxd.interview.sort.ChildTest;
import com.zxd.interview.sort.ParentTest;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.config.BeanFactoryPostProcessor;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.RootBeanDefinition;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.Lifecycle;
import org.springframework.context.support.ClassPathXmlApplicationContext;

/**
 * @author Xander
 * @version v1.0.0
 * @Package : com.zxd.interview.spring
 * @Description : demo测试案例
 * @Create on : 2023/8/7 16:06
 **/
public class ApplicationContextDemo {


    public class Student1 {

        private Student2 student2;

        //新增内容
//        public Student1(Student2 student2) {
//            this.student2 = student2;
//        }

        public Student2 getStudent2() {
            return student2;
        }
        public void setStudent2(Student2 student2) {
            this.student2 = student2;
        }
        @Override
        public String toString() {
            return "Student1{" +
                    "student2=" + student2 +
                    '}';
        }
    }

    public class Student2 {

        private Student1 student1;

        //新增内容
//        public Student2(Student1 student1) {
//            this.student1 = student1;
//        }

        public Student1 getStudent1() {
            return student1;
        }

        public void setStudent1(Student1 student1) {
            this.student1 = student1;
        }

        @Override
        public String toString() {
            return "Student2{" +
                    "student1=" + student1 +
                    '}';
        }
    }

    public static void main(String[] args) throws Exception {
//        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springconfig.xml");
//        AddTest student = (AddTest) applicationContext.getBean("student");
//        AddTest student2 = (AddTest) applicationContext.getBean("student2");
//        System.out.println("student => " + student);
//        System.out.println("student2 => "+ student2);
//
//        System.out.println("获取自定义Bean");
//        // 获取 MyBeanDefinitionRegistryPostProcessor 注册的自定义Bean
//        AddTest testBean = (AddTest) applicationContext.getBean("hello");
//        System.out.println(testBean);

//        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springconfig.xml");
//        applicationContext.getBean("student1");
//        applicationContext.getBean("student2");
//        AddTest bean = (AddTest) applicationContext.getBean("myFactoryBean");
//        FactoryBean factoryBean = (FactoryBean) applicationContext.getBean("&myFactoryBean");
//        System.out.println("bean = "+bean);
//        System.out.println("factoryBean = "+factoryBean);
//        System.out.println("factoryBean bean = "+factoryBean.getObject());

        ApplicationContext applicationContext = new ClassPathXmlApplicationContext("springconfig.xml");
        ParentTest parentTest = (ParentTest) applicationContext.getBean("parentTest");
        ChildTest childTest = (ChildTest) applicationContext.getBean("childTest");
        ParentTest parentTestChild = parentTest.getChild();
        ParentTest childTestChild = childTest.getChild();

        System.out.println("parentTest => " + parentTest);
        System.out.println("childTest => " + childTest);
        System.out.println("parentTest.getChild() => " + parentTestChild);
        System.out.println("childTest.getChild() => " + childTestChild);
        parentTest.testMethod();
        parentTestChild.testMethod();
        childTestChild.testMethod();
    }/**运行结果：
     student => com.zxd.interview.sort.AddTest@206a70ef
     student2 => com.zxd.interview.sort.AddTest@206a70ef

     com.zxd.interview.sort.AddTest@3c0be339

     获取自定义Bean
     com.zxd.interview.sort.AddTest@6a2b953e

     com.zxd.interview.sort.AddTest@cc43f62实例化完成
     com.zxd.interview.sort.AddTest@cc43f62开始实例化
     com.zxd.interview.sort.AddTest@5a5a729f开始实例化

     bean = com.zxd.interview.sort.AddTest@5a5a729f
     factoryBean = com.zxd.interview.spring.ApplicationContextDemo$MyFactoryBean@6f43c82
     factoryBean = com.zxd.interview.sort.AddTest@5db6b9cd

     // ==========================================================
     com.zxd.interview.sort.AddTest@5f20155b实例化完成
     com.zxd.interview.sort.AddTest@5f20155b开始实例化
     parentTest => com.zxd.interview.sort.ParentTest$$EnhancerBySpringCGLIB$$739dd0de@4066c471
     childTest => com.zxd.interview.sort.ChildTest@2b175c00
     调用抽象类
     getChild() => com.zxd.interview.sort.ChildTest@2b175c00
     parentTest.getChild() => com.zxd.interview.sort.ChildTest@2b175c00

     replace => Hello! from new method

     调用子类方法
     调用子类方法
     **/




    static class MyClassPathXmlApplicationContext extends ClassPathXmlApplicationContext{

        public MyClassPathXmlApplicationContext(String xmlFile){
            super(xmlFile);
        }

        @Override
        protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
            AddTest student = (AddTest) beanFactory.getBean("student");
            // 自定义 student 设置属性或者其他扩展。
            System.out.println("Bean都已经加载，但是尚未实例化");
            System.out.println(student);
            super.postProcessBeanFactory(beanFactory);
        }
    }

    public static class MyBeanDefinitionRegistryPostProcessor implements BeanDefinitionRegistryPostProcessor {

        @Override
        public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
            RootBeanDefinition helloBean = new RootBeanDefinition(AddTest.class);
            //新增Bean定义
            registry.registerBeanDefinition("hello", helloBean);
        }

        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

        }
    }

    /**
     *  自定义Factory B而安
     * @description 自定义Factory B而安
     * @param null
     * @return
     * @author Xander
     * @date 2023/8/25 7:19
     */
    public static class MyFactoryBean implements FactoryBean {
        @Override
        public Object getObject() throws Exception {
            AddTest addTest = new AddTest();
            return addTest;
        }

        @Override
        public Class<?> getObjectType() {
            return AddTest.class;
        }
    }


    public static class MyLifecycle implements Lifecycle {

        @Override
        public void start() {

            System.out.println("容器启动");
        }

        @Override
        public void stop() {

            System.out.println("容器关闭");
        }

        @Override
        public boolean isRunning() {
            return false;
        }
    }
    public static class MyBeanPostProcessor implements BeanPostProcessor {

        @Override
        public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
            if(bean instanceof AddTest){
                AddTest addTest = (AddTest) bean;
                System.out.println(addTest+ "开始实例化");
            }

            return bean;
        }

        @Override
        public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
            if(bean instanceof AddTest){
                AddTest addTest = (AddTest) bean;
                System.out.println(addTest+ "实例化完成");
            }
            return bean;
        }
    }/**运行结果
     com.zxd.interview.sort.AddTest@74e28667实例化完成
     com.zxd.interview.sort.AddTest@74e28667开始实例化
    */

    public static class MyEvent extends ApplicationEvent{

        public MyEvent(Object source) {
            super(source);
        }

        public void event(){
            System.out.println("自定义处理逻辑");
        }


    }

    public static class MyClassPathXmlApplicationContextByImpl implements BeanFactoryPostProcessor {

        @Override
        public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {
            AddTest student = (AddTest) beanFactory.getBean("student");
            // 自定义 student 设置属性或者其他扩展。
            System.out.println("Bean都已经加载，但是尚未实例化");
            System.out.println(student);
        }
    }

//    protected Object getSingleton(String beanName, boolean allowEarlyReference) {
//        // Quick check for existing instance without full singleton lock
//        // 快速检查现有实例，无需完全单例锁
//        Object singletonObject = this.singletonObjects.get(beanName);
//        // 如果Bean在缓存中找到，并且Bean已经完成实例化，直接返回
//        if (singletonObject != null || !isSingletonCurrentlyInCreation(beanName)) {
//            return singletonObject;
//        }
//        // 从早期单例缓存当中，找到初步完成实例化的单例Bean
//        singletonObject = this.earlySingletonObjects.get(beanName);
//        // 如果Bean早期单例已经创建好或者不允许早期引用，直接返回 （注意这里默认传递为 true）
//        if (singletonObject != null || !allowEarlyReference) {
//            return singletonObject;
//        }
//        //
//        ObjectFactory<?> singletonFactory = this.singletonFactories.get(beanName);
//        if (singletonFactory != null) {
//            singletonObject = singletonFactory.getObject();
//            this.earlySingletonObjects.put(beanName, singletonObject);
//            this.singletonFactories.remove(beanName);
//        }
//
//
//
//        return singletonObject;
//    }
}
